#include <iostream>
#include <string>

using namespace std;
class Shape {
public:
    Shape(int x, int y, string color) :
        x(x), y(y), color(color) {
    }
    Shape(const Shape *shape) {
        this->x     = shape->x;
        this->y     = shape->y;
        this->color = shape->color;
    }
    virtual ~Shape() {
    }
    int    x;
    int    y;
    string color;

    virtual Shape  *clone() = 0;
    friend ostream &operator<<(ostream &os, const Shape &shape);
};

ostream &operator<<(ostream &os, const Shape &shape) {
    cout << "Shape" << endl;
    cout << "- (x, y): " << shape.x << ", " << shape.y << endl;
    cout << "- color:" << shape.color << endl;
}

class Rectangle : public Shape {
public:
    Rectangle(int x, int y, int width, int height, string color) :
        Shape(x, y, color), width(width), height(height) {
    }
    Rectangle(const Rectangle *shape) :
        Shape(shape) {
        this->width  = shape->width;
        this->height = shape->height;
    }
    int width;
    int height;

    Shape *clone() override {
        return new Rectangle(this);
    }

    friend ostream &operator<<(ostream &os, const Rectangle &shape);
};

ostream &operator<<(ostream &os, const Rectangle &shape) {
    os << "Rectangle" << endl;
    os << "- (x, y): " << shape.x << ", " << shape.y << endl;
    os << "- width: " << shape.width << endl;
    os << "- height: " << shape.height << endl;
    os << "- color:" << shape.color << endl;
    return os;
}

class Circle : public Shape {
public:
    Circle(int x, int y, int radius, string color) :
        Shape(x, y, color), radius(radius) {
    }
    Circle(const Circle *shape) :
        Shape(shape) {
        this->radius = shape->radius;
    }
    int radius;

    Shape *clone() override {
        return new Circle(this);
    }

    friend ostream &operator<<(ostream &os, const Circle &shape);
};

ostream &operator<<(ostream &os, const Circle &shape) {
    os << "Circle" << endl;
    os << "- (x, y): " << shape.x << ", " << shape.y << endl;
    os << "- radius: " << shape.radius << endl;
    os << "- color:" << shape.color << endl;

    return os;
}

/**
 * @brief 客户代码
 *
 */
void client() {
    Rectangle rect(100, 100, 10, 20, "red");
    cout << rect;

    Rectangle *rect2 = static_cast<Rectangle *>(rect.clone());
    cout << *rect2 << endl;

    //
    Circle circle(100, 200, 15, "blue");
    cout << circle;
    Circle *rect3 = static_cast<Circle *>(circle.clone());
    cout << *rect3 << endl;
}

int main(int argc, char *argv[]) {
    client();
    return 0;
}